library(cluster)
package ‘cluster’ was built under R version 3.4.4
library(mclust)
package ‘mclust’ was built under R version 3.4.4    __  ___________    __  _____________
   /  |/  / ____/ /   / / / / ___/_  __/
  / /|_/ / /   / /   / / / /\__ \ / /   
 / /  / / /___/ /___/ /_/ /___/ // /    
/_/  /_/\____/_____/\____//____//_/    version 5.4.1
Type 'citation("mclust")' for citing this R package in publications.
library(lattice)
library(tidyverse)
package ‘tidyverse’ was built under R version 3.4.2── Attaching packages ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.2.1 ──
✔ ggplot2 2.2.1.9000     ✔ purrr   0.2.4     
✔ tibble  1.4.2          ✔ dplyr   0.7.5     
✔ tidyr   0.8.1          ✔ stringr 1.3.1     
✔ readr   1.1.1          ✔ forcats 0.3.0     
package ‘tibble’ was built under R version 3.4.3package ‘purrr’ was built under R version 3.4.2package ‘forcats’ was built under R version 3.4.3── Conflicts ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
✖ purrr::map()    masks mclust::map()
library(maptree)
Loading required package: rpart
package ‘rpart’ was built under R version 3.4.3
library(mice)
package ‘mice’ was built under R version 3.4.4
Attaching package: ‘mice’

The following object is masked from ‘package:tidyr’:

    complete

The following objects are masked from ‘package:base’:

    cbind, rbind
library(magrittr)

Attaching package: ‘magrittr’

The following object is masked from ‘package:purrr’:

    set_names

The following object is masked from ‘package:tidyr’:

    extract
library(mclust)
library(mice)
library(nFactors)
Loading required package: MASS

Attaching package: ‘MASS’

The following object is masked from ‘package:dplyr’:

    select

Loading required package: psych

Attaching package: ‘psych’

The following objects are masked from ‘package:ggplot2’:

    %+%, alpha

The following object is masked from ‘package:mclust’:

    sim

Loading required package: boot
package ‘boot’ was built under R version 3.4.1
Attaching package: ‘boot’

The following object is masked from ‘package:psych’:

    logit

The following object is masked from ‘package:lattice’:

    melanoma


Attaching package: ‘nFactors’

The following object is masked from ‘package:lattice’:

    parallel
library(poLCA)
Loading required package: scatterplot3d
package ‘scatterplot3d’ was built under R version 3.4.4
library(Rtsne)
library(corrplot)
package ‘corrplot’ was built under R version 3.4.2corrplot 0.84 loaded

1 Utility Functions

utility_histogramplotter <- function(x) {
  lattice::histogram( ~ x)
}
seg.summ <- function(data, groups) {
  aggregate(data, list(groups), function(x) mean(as.numeric(as.character(x))))
}
minmax <- function(x)
{
    return((x- min(x)) /(max(x)-min(x)))
}
plot_bi_plots <- function(df, y,...) {
  old.par = par()
  par(mar=c(5,4,5,2))
  on.exit(expr = 'par = old.par')
  prcomp(df) %>% biplot(col = c('gray', 'red'), cex = .8, main = y, ...)
}
adjust_q13 <- function(df){
  df %<>% 
    mutate(q13_visitfreq_social= (q13r1+q13r2+q13r3 +q13r11)/4,
           q13_visitfreq_music = (q13r4+q13r7+q13r8 +q13r9)/4,
           q13_visitfreq_video = (q13r5+q13r6+q13r10+q13r12)/4)
  df[,!str_detect(names(df),'q13r')]
}
adjust_q24 <- function(df){
  df %<>% 
    mutate(
      q24_tech_posatt = (q24r1+q24r2+q24r3+q24r5+q24r6)/5,
      q24_tech_enter = (q24r7+q24r8)/2,
      q24_tech_comm = (q24r10+q24r11+q24r12)/3,
      q24_tech_negatv = (q24r4+q24r9)/2
    )
  df[,!str_detect(names(df),'q24r')]
}
adjust_q25 <- function(df){
  df %<>% 
    mutate(
      q25_prsnlty_leader = (q25r1+q25r2+q25r3+q25r4)/4,
      q25_prsnlty_risk   = (q25r5+q25r7+q25r8)/3,
      q25_prsnlty_drive  = (q25r9+q25r10+q25r11+q25r12)/4,
      q25_prsnlty_follower = q25r6
    )
  df[,!str_detect(names(df),'q25r')]
}
adjust_q26 <- function(df){
  df %<>% 
    mutate(
      q26_shopsavvy_bargain =  (q26r3+q26r5)/2,
      q26_shopsavvy_brands = (q26r18+q26r7+q26r13+q26r14+q26r15)/5,
      q26_shopsavvy_earn2spend = (q26r13+q26r16+q26r4)/3,
      q26_shopsavvy_applover = (q26r17+q26r12+q26r10+q26r8+q26r6+q26r9)/6,
      q26_shopsavvy_children = q26r11,
    )
  df[,!str_detect(names(df),'q26r')]
}
adjust_q2 <- function(df){
  df %<>%
    mutate(
      q2_apple = ifelse(q2r1==1|q2r2==1,1,0),
      q2_andriod = q2r3,
      q2_windows = q2r6,
      q2_tablet = q2r8,
      q2_other = ifelse(q2r4==1|q2r5==1|q2r7==1|q2r9==1,1,0)
    )
  df[,!str_detect(names(df),'q2r')]
}
adjust_q4 <- function(df){
    df %<>%
    mutate(
      q4_use_music_apps =q4r1,
      q4_use_tv_apps =ifelse(q4r2==1|q4r3==1|q4r4==1,1,0),
      q4_use_game_apps =q4r5,
      q4_use_social_apps =q4r6,
      q4_use_news_apps =ifelse(q4r7==1|q4r9==1,1,0),
      q4_use_shop_apps =q4r8,
      q4_use_none_apps =q4r11
    )
  df[,!str_detect(names(df),'q4r')]
}
adjust_race <- function(df){
  df %>% 
    mutate(
      q54_white  = ifelse(q54==1,1,0),
      q54_black  = ifelse(q54==2,1,0),
      q54_asian  = ifelse(q54==3,1,0),
      q54_hawai  = ifelse(q54==4,1,0),
      q54_native =  ifelse(q54==5,1,0),
      q54_other  = ifelse(q54==6,1,0),
      q55_latino =  ifelse(q55==1,1,0)
    ) %>% 
    dplyr::select(-q54,-q55)
}
adjust_gender <- function(df){
  df %>% 
    mutate(q57 = ifelse(q57==1,1,0))
}
adjust_marital <- function(df){
  df %>% 
    mutate(q49 = ifelse(q49==1,1,0))
}
adjust_q11 <- function(df){
  #Q11 has artificial ordinality between #of apps increasing, and response==5 as "Dont know"
  #This function resolves this problem
  df %>% 
    mutate(q11 = ifelse(q11==5 | q11==6, 0, q11))
}
adjust_children <- function(df){
  df %>% 
    dplyr::select(-q50r2_inftod,-q50r3_6_12,-q50r4_13_17,-q50r5_adult)
}
adjust_income <- function(df){
  df %>% 
    dplyr::mutate(q56 = case_when(
      q56 <= 4 ~ 1,
      q56 >= 5 & q56 <=8 ~ 2,
      q56 >= 9 & q56 <=11 ~ 3,
      q56 >= 12 & q56 <= 13 ~ 4,
      q56 >= 14 ~ 5
    ))
}
adjust_age <- function(df){
  df %>% 
    dplyr::mutate(
      q1 = case_when(
        q1 <= 2 ~ 1,
        q1 >= 3 & q1 <= 5 ~ 2,
        q1 >= 6 & q1 <= 8 ~ 3,
        q1 >= 9 & q1 <= 11 ~ 4,
        q1 >= 12 ~ 5,
      )
    )
}
adjust_names <- function(df){
  df %>% 
    dplyr::rename(
      q1_age=q1,
      q11_appnum = q11,
      q12_freeapppc = q12,
      q48_edu = q48,
      q49_marital = q49,
      q56_income = q56,
      q57_mf = q57,
      q50r1_nochild = q50r1,
      q50r2_inftod = q50r2, 
      q50r3_6_12 = q50r3,
      q50r4_13_17 = q50r4,
      q50r5_adult = q50r5
    )
}

2 Data Prep

load('../data/apphappyData.RData')
df_labs <- tbl_df(apphappy.3.labs.frame)
df_nums <- tbl_df(apphappy.3.num.frame)
dim(df_nums)
[1] 1800   89
rm(apphappy.3.num.frame); rm(apphappy.3.labs.frame)
df_labs$q57 <- as.factor(df_labs$q57)
df_labs$caseID <- NULL
df_nums$caseID <- NULL
df_labs$q2r10 <- NULL
df_nums$q2r10 <- NULL
df_labs$q5r1 <- NULL
df_nums$q5r1 <- NULL

3 Remove missing values

3.1 Handle the case of the missing apps?

df_nums$q12[is.na(df_nums$q12)] <- 0
df_nums %>% xtabs(~q12+q11,.,addNA = T)
   q11
q12   1   2   3   4   5   6
  0   0   0   0   0   0  24
  1   6   9   5   3   1   0
  2  31  56  48  66   2   0
  3  23  42 117 114  11   0
  4  12  44 150 198  12   0
  5  23  44 158 209  20   0
  6  68  78 131  71  24   0
df_nums %>% xtabs(~q4r10+q11,.,addNA = T)
     q11
q4r10   1   2   3   4   5   6
    0 156 254 564 595  67  24
    1   7  19  45  66   3   0
df_nums %>% xtabs(~q4r11+q11,.,addNA = T)
     q11
q4r11   1   2   3   4   5   6
    0 148 267 606 661  65   8
    1  15   6   3   0   5  16
# RULE (A): IF q4r11=TRUE, it means you have no apps. So that means q11 has to equal 6, i.e. NONE. Data shows this is violated. Correcting using this rule.
df_nums$q11[df_nums$q4r11==TRUE] <- 6
df_nums %>% xtabs(~q4r11+q11,.,addNA = T)
     q11
q4r11   1   2   3   4   5   6
    0 148 267 606 661  65   8
    1   0   0   0   0   0  45

3.2 Small changes

Since q11 can be ordinal, “none” should equal 0 instead of 6 to preserve ordinality

# RULE (B): Set q11=6 to q11=0
df_nums$q11[df_nums$q11==6] <- 0
df_nums %>% xtabs(~q11,., addNA = T)
q11
  0   1   2   3   4   5 
 53 148 267 606 661  65 

‘Dont know’ doesn’t add value. Perhaps these can be set to NA and then imputed using mice.

# RULE (C): Set q11 Dont know to NA
df_nums$q11[df_nums$q11==0] <- NA
df_nums %>% xtabs(~q11,., addNA = T)
q11
   1    2    3    4    5 <NA> 
 148  267  606  661   65   53 
# RULE (D): All NA values for q12 set to 6, since I'm approximating that if you don't have any apps, might as well could as free?
df_nums$q12[is.na(df_nums$q12)] <- 6
df_nums %>% xtabs(~q12,., addNA = T)
q12
  0   1   2   3   4   5   6 
 24  24 203 307 416 454 372 
map_int(df_nums,~sum(is.na(.x))) %>% sort() %>% tail(3) %>% barchart(main='Missing values')

3.3 Imputing using mice

map_df(df_nums,~as.factor(.x)) %>% 
  mice::mice(printFlag = T, m = 5, method = 'rf') -> miceFit

 iter imp variable
  1   1  q11  q57
  1   2  q11  q57
  1   3  q11  q57
  1   4  q11  q57
  1   5  q11  q57
  2   1  q11  q57
  2   2  q11  q57
  2   3  q11  q57
  2   4  q11  q57
  2   5  q11  q57
  3   1  q11  q57
  3   2  q11  q57
  3   3  q11  q57
  3   4  q11  q57
  3   5  q11  q57
  4   1  q11  q57
  4   2  q11  q57
  4   3  q11  q57
  4   4  q11  q57
  4   5  q11  q57
  5   1  q11  q57
  5   2  q11  q57
  5   3  q11  q57
  5   4  q11  q57
  5   5  q11  q57
unknown timezone 'default/America/Indiana/Indianapolis'Number of logged events: 25
df_nums <- tbl_df(mice::complete(miceFit))

4 Bi Plots

# questions_to_consolidate <- c('q13','q24','q25','q26')
# plot_bi_plots(df_nums %>% dplyr::select(contains(questions_to_consolidate[1])),questions_to_consolidate[1])
# plot_bi_plots(df_nums %>% dplyr::select(contains(questions_to_consolidate[2])),questions_to_consolidate[2], xlim=c(0,.05), ylim=c(-0.01,0.002))
# plot_bi_plots(df_nums %>% dplyr::select(contains(questions_to_consolidate[3])),questions_to_consolidate[3])
# plot_bi_plots(df_nums %>% dplyr::select(contains(questions_to_consolidate[4])),questions_to_consolidate[4], xlim=c(0,0.05),ylim=c(-0.011,0.005))

5 Data Prep

5.1 Sub grouping

df_nums <- map_df(df_nums,~as.numeric(as.character(.x)))
df_nums_adj <- df_nums %>%  
  adjust_q13() %>% 
  adjust_q24() %>% 
  adjust_q25() %>% 
  adjust_q26() %>% 
  adjust_q2() %>% 
  adjust_q4() %>% 
  adjust_race() %>% 
  adjust_gender() %>% 
  adjust_marital() %>% 
  adjust_income() %>%
  adjust_age() %>% 
  adjust_q11() %>% 
  adjust_names() %>% 
  adjust_children()
package ‘bindrcpp’ was built under R version 3.4.4
glimpse(df_nums_adj)
Observations: 1,800
Variables: 43
$ q1_age                   <dbl> 1, 1, 3, 1, 2, 1, 2, 2, 2, 2, 2, 1, 1, 3, 1, 3, 2, 2, 1, 2, 1, 2, 4, 3, 2, 1, 1, 2, 2, 1, 2, 3, 2, 3, 1, 1, 2, 1, 1, 2, 2, 1, 2, 3, 2, 4, 2,...
$ q11_appnum               <dbl> 4, 3, 3, 4, 3, 4, 4, 3, 1, 2, 3, 2, 4, 4, 4, 3, 4, 3, 4, 4, 2, 4, 1, 4, 4, 1, 3, 3, 3, 4, 3, 4, 3, 1, 2, 3, 2, 4, 4, 0, 4, 3, 4, 3, 4, 4, 3,...
$ q12_freeapppc            <dbl> 5, 5, 6, 4, 6, 3, 3, 6, 5, 2, 5, 6, 2, 3, 5, 4, 2, 2, 3, 5, 3, 6, 2, 5, 4, 3, 4, 0, 4, 4, 3, 4, 5, 6, 6, 2, 6, 3, 5, 5, 3, 4, 2, 6, 4, 2, 6,...
$ q48_edu                  <dbl> 3, 4, 3, 4, 4, 1, 3, 4, 3, 3, 4, 3, 4, 3, 4, 3, 2, 4, 6, 6, 1, 5, 3, 4, 6, 1, 3, 2, 2, 3, 3, 3, 3, 4, 3, 2, 3, 3, 4, 2, 4, 3, 6, 4, 3, 4, 4,...
$ q49_marital              <dbl> 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1,...
$ q50r1_nochild            <dbl> 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0,...
$ q56_income               <dbl> 2, 3, 4, 2, 2, 1, 1, 3, 2, 2, 2, 2, 4, 3, 2, 4, 3, 2, 2, 2, 2, 4, 3, 3, 5, 1, 2, 2, 1, 2, 3, 3, 2, 3, 1, 2, 3, 1, 1, 2, 2, 2, 3, 1, 4, 5, 3,...
$ q57_mf                   <dbl> 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1,...
$ q13_visitfreq_social     <dbl> 2.50, 3.00, 3.25, 4.00, 2.50, 4.00, 2.50, 2.25, 2.75, 2.00, 2.75, 3.25, 1.25, 3.25, 2.00, 2.25, 2.75, 2.00, 2.75, 3.25, 3.25, 3.25, 4.00, 2....
$ q13_visitfreq_music      <dbl> 3.75, 3.50, 2.75, 3.25, 3.50, 3.50, 4.00, 2.50, 2.00, 1.25, 3.50, 3.25, 1.75, 3.25, 2.50, 3.75, 2.50, 2.75, 4.00, 3.25, 2.50, 2.50, 2.75, 3....
$ q13_visitfreq_video      <dbl> 2.50, 2.00, 2.50, 2.50, 1.75, 2.25, 3.25, 3.25, 2.00, 1.25, 3.50, 2.00, 1.50, 3.25, 2.25, 3.00, 1.75, 2.00, 3.25, 1.75, 3.25, 2.00, 3.25, 2....
$ q24_tech_posatt          <dbl> 2.8, 2.8, 3.0, 3.0, 2.2, 3.4, 2.8, 2.0, 2.6, 2.8, 2.2, 2.0, 1.4, 2.6, 2.8, 2.2, 1.0, 3.6, 1.0, 2.6, 1.0, 3.2, 4.4, 2.6, 2.0, 2.2, 1.0, 2.4, ...
$ q24_tech_enter           <dbl> 2.0, 2.0, 1.5, 3.0, 2.5, 1.0, 2.5, 2.0, 3.0, 2.5, 2.5, 1.0, 1.5, 2.0, 1.5, 1.5, 1.0, 1.5, 2.5, 2.5, 1.0, 1.0, 4.5, 2.0, 2.5, 3.0, 1.0, 4.5, ...
$ q24_tech_comm            <dbl> 2.666667, 1.333333, 2.666667, 3.666667, 3.333333, 1.000000, 3.000000, 2.333333, 3.000000, 2.333333, 4.333333, 1.000000, 2.000000, 1.666667, ...
$ q24_tech_negatv          <dbl> 1.0, 3.0, 4.5, 3.0, 1.5, 4.5, 1.5, 4.0, 4.5, 3.0, 5.5, 6.0, 2.0, 5.0, 3.5, 5.0, 1.0, 2.0, 4.0, 3.5, 1.0, 4.0, 4.0, 3.5, 2.0, 3.0, 1.0, 2.5, ...
$ q25_prsnlty_leader       <dbl> 1.50, 2.75, 2.50, 2.00, 3.25, 3.00, 3.00, 3.25, 2.75, 2.00, 2.00, 1.00, 1.25, 2.25, 1.50, 2.25, 1.25, 2.50, 1.75, 2.50, 2.75, 1.50, 4.75, 3....
$ q25_prsnlty_risk         <dbl> 1.666667, 2.333333, 3.333333, 2.666667, 3.666667, 3.000000, 1.666667, 3.000000, 3.000000, 2.333333, 2.666667, 1.333333, 1.333333, 3.000000, ...
$ q25_prsnlty_drive        <dbl> 2.75, 2.25, 2.00, 3.25, 3.00, 2.50, 2.50, 2.25, 2.75, 2.25, 3.00, 1.00, 1.75, 3.00, 1.50, 3.00, 2.25, 2.50, 1.50, 1.00, 2.25, 2.50, 2.00, 3....
$ q25_prsnlty_follower     <dbl> 5, 5, 6, 5, 4, 4, 2, 5, 5, 2, 6, 5, 2, 6, 5, 6, 3, 1, 4, 5, 3, 5, 6, 6, 2, 5, 1, 5, 5, 3, 4, 6, 4, 6, 6, 2, 5, 3, 4, 5, 5, 5, 6, 6, 6, 5, 3,...
$ q26_shopsavvy_bargain    <dbl> 2.5, 3.5, 3.0, 3.0, 3.0, 3.0, 3.5, 1.5, 3.5, 1.5, 2.5, 2.0, 1.5, 3.5, 3.5, 2.5, 1.0, 3.0, 3.5, 2.0, 3.5, 1.5, 3.5, 3.5, 2.5, 3.5, 1.0, 3.5, ...
$ q26_shopsavvy_brands     <dbl> 3.4, 3.2, 3.4, 3.0, 4.0, 3.2, 2.8, 3.8, 5.4, 1.4, 4.4, 3.6, 2.0, 3.6, 2.8, 4.6, 1.4, 2.0, 2.0, 3.0, 3.6, 4.6, 4.0, 4.4, 2.0, 4.6, 1.0, 5.8, ...
$ q26_shopsavvy_earn2spend <dbl> 2.666667, 3.333333, 3.666667, 3.666667, 4.000000, 4.000000, 5.000000, 3.000000, 5.333333, 1.000000, 3.666667, 3.666667, 2.333333, 4.333333, ...
$ q26_shopsavvy_applover   <dbl> 4.166667, 3.000000, 4.166667, 2.166667, 3.666667, 2.166667, 3.000000, 4.000000, 4.833333, 1.666667, 4.166667, 3.000000, 2.000000, 2.666667, ...
$ q26_shopsavvy_children   <dbl> 6, 6, 4, 6, 3, 5, 5, 6, 5, 1, 6, 6, 1, 3, 6, 2, 1, 3, 1, 4, 5, 6, 3, 5, 2, 5, 1, 6, 5, 5, 3, 4, 2, 3, 6, 2, 6, 6, 3, 4, 5, 3, 5, 3, 6, 5, 1,...
$ q2_apple                 <dbl> 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0,...
$ q2_andriod               <dbl> 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1,...
$ q2_windows               <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,...
$ q2_tablet                <dbl> 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,...
$ q2_other                 <dbl> 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,...
$ q4_use_music_apps        <dbl> 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
$ q4_use_tv_apps           <dbl> 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0,...
$ q4_use_game_apps         <dbl> 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0,...
$ q4_use_social_apps       <dbl> 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
$ q4_use_news_apps         <dbl> 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1,...
$ q4_use_shop_apps         <dbl> 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1,...
$ q4_use_none_apps         <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ q54_white                <dbl> 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
$ q54_black                <dbl> 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ q54_asian                <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ q54_hawai                <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ q54_native               <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ q54_other                <dbl> 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ q55_latino               <dbl> 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...

5.2 Selection of basis variables

set1 <- c(
  'q1_age',
  # 'q11_appnum',
  # 'q12_freeapppc',
  'q48_edu',
  'q49_marital',
  'q50r1_nochild',
  'q56_income',
  # 'q57_mf',
  # 'q13_visitfreq_social',
  # 'q13_visitfreq_music',
  # 'q13_visitfreq_video',
  'q24_tech_posatt',
  'q24_tech_enter',
  'q24_tech_comm',
  'q24_tech_negatv',
  # 'q25_prsnlty_leader',
  # 'q25_prsnlty_risk',
  # 'q25_prsnlty_drive',
  # 'q25_prsnlty_follower',
  'q26_shopsavvy_bargain',
  'q26_shopsavvy_brands',
  'q26_shopsavvy_earn2spend',
  'q26_shopsavvy_applover',
  'q26_shopsavvy_children',
  'q2_apple',
  'q2_andriod',
  'q2_windows',
  # 'q2_tablet',
  # 'q2_other',
  # 'q4_use_music_apps',
  # 'q4_use_tv_apps',
  # 'q4_use_game_apps',
  # 'q4_use_social_apps',
  # 'q4_use_news_apps',
  # 'q4_use_shop_apps',
  # 'q4_use_none_apps',
  'q54_white',
  'q54_black',
  'q54_asian',
  'q54_hawai',
  'q54_native',
  # 'q54_other',
  'q55_latino'
  )
set2 <- c(
  'q1_age',
  # 'q11_appnum',
  'q12_freeapppc',
  'q48_edu',
  'q49_marital',
  'q50r1_nochild',
  'q56_income',
  # 'q57_mf',
  'q13_visitfreq_social',
  'q13_visitfreq_music',
  'q13_visitfreq_video',
  'q24_tech_posatt',
  'q24_tech_enter',
  'q24_tech_comm',
  'q24_tech_negatv',
  'q25_prsnlty_leader',
  'q25_prsnlty_risk',
  'q25_prsnlty_drive',
  'q25_prsnlty_follower',
  'q26_shopsavvy_bargain',
  'q26_shopsavvy_brands',
  'q26_shopsavvy_earn2spend',
  'q26_shopsavvy_applover',
  'q26_shopsavvy_children',
  # 'q2_apple',
  # 'q2_andriod',
  # 'q2_windows',
  # 'q2_tablet',
  # 'q2_other',
  # 'q4_use_music_apps',
  # 'q4_use_tv_apps',
  # 'q4_use_game_apps',
  # 'q4_use_social_apps',
  # 'q4_use_news_apps',
  # 'q4_use_shop_apps',
  # 'q4_use_none_apps',
  'q54_white',
  'q54_black',
  'q54_asian',
  'q54_hawai',
  'q54_native',
  # 'q54_other',
  'q55_latino'
  )
set3 <- c(
  'q1_age',
  'q11_appnum',
  'q12_freeapppc',
  'q48_edu',
  'q49_marital',
  'q50r1_nochild',
  'q56_income',
  'q57_mf',
  # 'q13_visitfreq_social',
  # 'q13_visitfreq_music',
  # 'q13_visitfreq_video',
  # 'q24_tech_posatt',
  # 'q24_tech_enter',
  # 'q24_tech_comm',
  # 'q24_tech_negatv',
  # 'q25_prsnlty_leader',
  # 'q25_prsnlty_risk',
  # 'q25_prsnlty_drive',
  # 'q25_prsnlty_follower',
  'q26_shopsavvy_bargain',
  'q26_shopsavvy_brands',
  'q26_shopsavvy_earn2spend',
  'q26_shopsavvy_applover',
  'q26_shopsavvy_children',
  'q2_apple',
  'q2_andriod',
  'q2_windows',
  'q2_tablet',
  'q2_other',
  'q4_use_music_apps',
  'q4_use_tv_apps',
  'q4_use_game_apps',
  'q4_use_social_apps',
  'q4_use_news_apps',
  'q4_use_shop_apps',
  'q4_use_none_apps'
  # 'q54_white',
  # 'q54_black',
  # 'q54_asian',
  # 'q54_hawai',
  # 'q54_native',
  # 'q54_other',
  # 'q55_latino'
  )
set4 <- c(
  'q1_age',
  # 'q11_appnum',
  # 'q12_freeapppc',
  # 'q48_edu',
  'q49_marital',
  'q50r1_nochild',
  'q56_income',
  'q57_mf',
  'q13_visitfreq_social',
  'q13_visitfreq_music',
  'q13_visitfreq_video',
  'q24_tech_posatt',
  'q24_tech_enter',
  'q24_tech_comm',
  'q24_tech_negatv',
  'q25_prsnlty_leader',
  'q25_prsnlty_risk',
  'q25_prsnlty_drive',
  'q25_prsnlty_follower',
  'q26_shopsavvy_bargain',
  'q26_shopsavvy_brands',
  'q26_shopsavvy_earn2spend',
  'q26_shopsavvy_applover',
  'q26_shopsavvy_children'
  # 'q2_apple',
  # 'q2_andriod',
  # 'q2_windows',
  # 'q2_tablet',
  # 'q2_other',
  # 'q4_use_music_apps',
  # 'q4_use_tv_apps',
  # 'q4_use_game_apps',
  # 'q4_use_social_apps',
  # 'q4_use_news_apps',
  # 'q4_use_shop_apps',
  # 'q4_use_none_apps'
  # 'q54_white',
  # 'q54_black',
  # 'q54_asian',
  # 'q54_hawai',
  # 'q54_native',
  # 'q54_other',
  # 'q55_latino'
  )
df_nums_adj_backup <- df_nums_adj
df_nums_adj <- df_nums_adj_backup
df_nums_adj <- df_nums_adj %>% dplyr::select(one_of(set4))

6 Scaling

scaling_wanted <- T
minmax_wanted <- F
if (scaling_wanted) {
  df_nums_adjscaled <- scale(df_nums_adj)
  centers <- attributes(df_nums_adjscaled)[[3]]
  spreads <- attributes(df_nums_adjscaled)[[4]]
  df_nums_adjscaled <- tbl_df(df_nums_adjscaled)
}
if(minmax_wanted){
  df_nums_adjscaled <- map_df(df_nums_adj, ~minmax(.x))
}
if(!scaling_wanted & !minmax_wanted){
  df_nums_adjscaled <- df_nums_adj
}
head(df_nums_adjscaled)

7 Correlation Plot

df_nums_adjscaled %>% cor() %>% corrplot(method = 'shade',tl.col = 'black',tl.cex = .9, order = 'hclust', hclust.method = 'ward.D2')

8 Dissimilarity Calculations

# ordered=c(1:4,11,13:28)
# symm_bin=c(6:10,12,29:47)
# df_nums_adjscaled[ordered] <- map_df(df_nums_adjscaled[ordered],~as.ordered(.x))
# df_nums_adjscaled[symm_bin] <- map_df(df_nums_adjscaled[symm_bin],~as.factor(.x))
distMat <- daisy(df_nums_adjscaled)
binary variable(s) 2, 3, 5 treated as interval scaled

9 Simple clustering

9.1 H clust

9.1.1 How cophenetic changes with clustering method?

methods <- c('complete','average','ward.D','ward.D2','median','mcquitty','centroid')
method_vs_cop <- map_dbl(methods,~cor(cophenetic(hclust(d = distMat, method = .x)), distMat))
names(method_vs_cop) <- methods
barchart(sort(method_vs_cop))

k = 6
hclustFit <- hclust(d = distMat, method = 'ward.D')
plot(hclustFit, labels = F)
rect.hclust(hclustFit, k=k, border="red")

hclust_segments <- cutree(hclustFit, k = k)
table(hclust_segments)
hclust_segments
  1   2   3   4   5   6 
341 412 333 217 126 371 
clusplot(df_nums_adjscaled, hclust_segments, color=TRUE, shade=TRUE, labels=4, lines=0, main="HClust plot")

seg.summ(df_nums_adj, hclust_segments) -> centroids
centroids
cutFit <- cutree(hclustFit, k)
plot(silhouette(cutFit,distMat))

k <- 2:10
widths <- NULL
for(k_ in k){
  hclustFit <- hclust(d = distMat, method = 'ward.D')
  cutFit <- cutree(hclustFit, k_)
  widths <- c(widths,mean(silhouette(cutFit,distMat)[,'sil_width']))
}
plot(k,widths,type='b')

cbind(k,widths)
       k     widths
 [1,]  2 0.13737473
 [2,]  3 0.08281616
 [3,]  4 0.06855129
 [4,]  5 0.06137392
 [5,]  6 0.05921532
 [6,]  7 0.06267068
 [7,]  8 0.06064109
 [8,]  9 0.05293374
 [9,] 10 0.04584471

9.2 K-means

9.2.1 How many clusters to use?

wssplot <- function(numsub, nc=15, seed=1111) {
  wss <- (nrow(numsub)-1)*sum(apply(numsub,2,var))
  for (i in 2:nc) {
    set.seed(seed)
    wss[i] <- sum(kmeans(numsub, centers=i, iter.max = 1e4)$withinss)}
  plot(1:nc, wss, type="b", xlab="Number of Clusters",
       ylab="Within groups sum of squares")}
wssplot(df_nums_adjscaled)

9.2.2 Solving the k-means model

k <- 2:10
widths <- NULL
for(k_ in k){
  clusterresults <- kmeans(x = df_nums_adjscaled, centers = k_, nstart = 30)
  widths <- c(widths,mean(silhouette(clusterresults$cluster,distMat)[,'sil_width']))
}
did not converge in 10 iterations
plot(k,widths,type='b')

cbind(k,widths)
       k     widths
 [1,]  2 0.15626749
 [2,]  3 0.10919911
 [3,]  4 0.10576895
 [4,]  5 0.10285049
 [5,]  6 0.09506744
 [6,]  7 0.09259923
 [7,]  8 0.08744827
 [8,]  9 0.08373856
 [9,] 10 0.08123470
# Using cluster centers from hclust:
seg.summ(df_nums_adjscaled, hclust_segments) -> kmeans_centroids
clusterresults <- kmeans(x = df_nums_adjscaled, centers = kmeans_centroids[,-1])
rsquare <- clusterresults$betweenss/clusterresults$totss
cat('\nWithin SS:',clusterresults$withinss,' Sizes:\n',clusterresults$size,'\nrsq:', rsquare)

Within SS: 4949.8 5143.576 3741.233 3415.204 2907.519 4511.912  Sizes:
 383 395 220 254 223 325 
rsq: 0.3470117
clusplot(df_nums_adjscaled, clusterresults$cluster, color=TRUE, shade=TRUE, labels=4, lines=0, main="K-means cluster plot")

plot(silhouette(clusterresults$cluster,distMat))

purrr::map2(kmeans_results, names(kmeans_results),
            ~bwplot(cluster~.x, kmeans_results,
                    main=.y))
$q1_age

$q49_marital

$q50r1_nochild

$q56_income

$q57_mf

$q13_visitfreq_social

$q13_visitfreq_music

$q13_visitfreq_video

$q24_tech_posatt

$q24_tech_enter

$q24_tech_comm

$q24_tech_negatv

$q25_prsnlty_leader

$q25_prsnlty_risk

$q25_prsnlty_drive

$q25_prsnlty_follower

$q26_shopsavvy_bargain

$q26_shopsavvy_brands

$q26_shopsavvy_earn2spend

$q26_shopsavvy_applover

$q26_shopsavvy_children

$cluster

9.3 PAM

pamFits <- tibble(k_pam = 2:10)
pamFits$pamFits <- map(pamFits$k_pam, ~pam(df_nums_adjscaled, k = .x))
pamFits$sil_avg_width <- map_dbl(pamFits$pamFits,~.x$silinfo$avg.width)
pamFits
pamFits %>% 
  xyplot(sil_avg_width~as.factor(k_pam),.,type='b')

plot(pamFits$pamFits[[1]])

seg.summ(df_nums_adj, pamFits$pamFits[[1]]$clustering)

10 Model based

mclustFits <- tibble(mclust_clusters=2:8)
mclustFits$mclustFits <- map(mclustFits$mclust_clusters, ~Mclust(df_nums_adjscaled, G = .x))
fitting ...

  |                                                                                                                                                                              
  |                                                                                                                                                                        |   0%
  |                                                                                                                                                                              
  |===========                                                                                                                                                             |   7%
  |                                                                                                                                                                              
  |======================                                                                                                                                                  |  13%
  |                                                                                                                                                                              
  |==================================                                                                                                                                      |  20%
  |                                                                                                                                                                              
  |=============================================                                                                                                                           |  27%
  |                                                                                                                                                                              
  |========================================================                                                                                                                |  33%
  |                                                                                                                                                                              
  |===================================================================                                                                                                     |  40%
  |                                                                                                                                                                              
  |==============================================================================                                                                                          |  47%
  |                                                                                                                                                                              
  |==========================================================================================                                                                              |  53%
  |                                                                                                                                                                              
  |=====================================================================================================                                                                   |  60%
  |                                                                                                                                                                              
  |================================================================================================================                                                        |  67%
  |                                                                                                                                                                              
  |===========================================================================================================================                                             |  73%
  |                                                                                                                                                                              
  |======================================================================================================================================                                  |  80%
  |                                                                                                                                                                              
  |==================================================================================================================================================                      |  87%
  |                                                                                                                                                                              
  |=============================================================================================================================================================           |  93%
  |                                                                                                                                                                              
  |========================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                              
  |                                                                                                                                                                        |   0%
  |                                                                                                                                                                              
  |===========                                                                                                                                                             |   7%
  |                                                                                                                                                                              
  |======================                                                                                                                                                  |  13%
  |                                                                                                                                                                              
  |==================================                                                                                                                                      |  20%
  |                                                                                                                                                                              
  |=============================================                                                                                                                           |  27%
  |                                                                                                                                                                              
  |========================================================                                                                                                                |  33%
  |                                                                                                                                                                              
  |===================================================================                                                                                                     |  40%
  |                                                                                                                                                                              
  |==============================================================================                                                                                          |  47%
  |                                                                                                                                                                              
  |==========================================================================================                                                                              |  53%
  |                                                                                                                                                                              
  |=====================================================================================================                                                                   |  60%
  |                                                                                                                                                                              
  |================================================================================================================                                                        |  67%
  |                                                                                                                                                                              
  |===========================================================================================================================                                             |  73%
  |                                                                                                                                                                              
  |======================================================================================================================================                                  |  80%
  |                                                                                                                                                                              
  |==================================================================================================================================================                      |  87%
  |                                                                                                                                                                              
  |=============================================================================================================================================================           |  93%
  |                                                                                                                                                                              
  |========================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                              
  |                                                                                                                                                                        |   0%
  |                                                                                                                                                                              
  |===========                                                                                                                                                             |   7%
  |                                                                                                                                                                              
  |======================                                                                                                                                                  |  13%
  |                                                                                                                                                                              
  |==================================                                                                                                                                      |  20%
  |                                                                                                                                                                              
  |=============================================                                                                                                                           |  27%
  |                                                                                                                                                                              
  |========================================================                                                                                                                |  33%
  |                                                                                                                                                                              
  |===================================================================                                                                                                     |  40%
  |                                                                                                                                                                              
  |==============================================================================                                                                                          |  47%
  |                                                                                                                                                                              
  |==========================================================================================                                                                              |  53%
  |                                                                                                                                                                              
  |=====================================================================================================                                                                   |  60%
  |                                                                                                                                                                              
  |================================================================================================================                                                        |  67%
  |                                                                                                                                                                              
  |===========================================================================================================================                                             |  73%
  |                                                                                                                                                                              
  |======================================================================================================================================                                  |  80%
  |                                                                                                                                                                              
  |==================================================================================================================================================                      |  87%
  |                                                                                                                                                                              
  |=============================================================================================================================================================           |  93%
  |                                                                                                                                                                              
  |========================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                              
  |                                                                                                                                                                        |   0%
  |                                                                                                                                                                              
  |===========                                                                                                                                                             |   7%
  |                                                                                                                                                                              
  |======================                                                                                                                                                  |  13%
  |                                                                                                                                                                              
  |==================================                                                                                                                                      |  20%
  |                                                                                                                                                                              
  |=============================================                                                                                                                           |  27%
  |                                                                                                                                                                              
  |========================================================                                                                                                                |  33%
  |                                                                                                                                                                              
  |===================================================================                                                                                                     |  40%
  |                                                                                                                                                                              
  |==============================================================================                                                                                          |  47%
  |                                                                                                                                                                              
  |==========================================================================================                                                                              |  53%
  |                                                                                                                                                                              
  |=====================================================================================================                                                                   |  60%
  |                                                                                                                                                                              
  |================================================================================================================                                                        |  67%
  |                                                                                                                                                                              
  |===========================================================================================================================                                             |  73%
  |                                                                                                                                                                              
  |======================================================================================================================================                                  |  80%
  |                                                                                                                                                                              
  |==================================================================================================================================================                      |  87%
  |                                                                                                                                                                              
  |=============================================================================================================================================================           |  93%
  |                                                                                                                                                                              
  |========================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                              
  |                                                                                                                                                                        |   0%
  |                                                                                                                                                                              
  |===========                                                                                                                                                             |   7%
  |                                                                                                                                                                              
  |======================                                                                                                                                                  |  13%
  |                                                                                                                                                                              
  |==================================                                                                                                                                      |  20%
  |                                                                                                                                                                              
  |=============================================                                                                                                                           |  27%
  |                                                                                                                                                                              
  |========================================================                                                                                                                |  33%
  |                                                                                                                                                                              
  |===================================================================                                                                                                     |  40%
  |                                                                                                                                                                              
  |==============================================================================                                                                                          |  47%
  |                                                                                                                                                                              
  |==========================================================================================                                                                              |  53%
  |                                                                                                                                                                              
  |=====================================================================================================                                                                   |  60%
  |                                                                                                                                                                              
  |================================================================================================================                                                        |  67%
  |                                                                                                                                                                              
  |===========================================================================================================================                                             |  73%
  |                                                                                                                                                                              
  |======================================================================================================================================                                  |  80%
  |                                                                                                                                                                              
  |==================================================================================================================================================                      |  87%
  |                                                                                                                                                                              
  |=============================================================================================================================================================           |  93%
  |                                                                                                                                                                              
  |========================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                              
  |                                                                                                                                                                        |   0%
  |                                                                                                                                                                              
  |===========                                                                                                                                                             |   7%
  |                                                                                                                                                                              
  |======================                                                                                                                                                  |  13%
  |                                                                                                                                                                              
  |==================================                                                                                                                                      |  20%
  |                                                                                                                                                                              
  |=============================================                                                                                                                           |  27%
  |                                                                                                                                                                              
  |========================================================                                                                                                                |  33%
  |                                                                                                                                                                              
  |===================================================================                                                                                                     |  40%
  |                                                                                                                                                                              
  |==============================================================================                                                                                          |  47%
  |                                                                                                                                                                              
  |==========================================================================================                                                                              |  53%
  |                                                                                                                                                                              
  |=====================================================================================================                                                                   |  60%
  |                                                                                                                                                                              
  |================================================================================================================                                                        |  67%
  |                                                                                                                                                                              
  |===========================================================================================================================                                             |  73%
  |                                                                                                                                                                              
  |======================================================================================================================================                                  |  80%
  |                                                                                                                                                                              
  |==================================================================================================================================================                      |  87%
  |                                                                                                                                                                              
  |=============================================================================================================================================================           |  93%
  |                                                                                                                                                                              
  |========================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                              
  |                                                                                                                                                                        |   0%
  |                                                                                                                                                                              
  |===========                                                                                                                                                             |   7%
  |                                                                                                                                                                              
  |======================                                                                                                                                                  |  13%
  |                                                                                                                                                                              
  |==================================                                                                                                                                      |  20%
  |                                                                                                                                                                              
  |=============================================                                                                                                                           |  27%
  |                                                                                                                                                                              
  |========================================================                                                                                                                |  33%
  |                                                                                                                                                                              
  |===================================================================                                                                                                     |  40%
  |                                                                                                                                                                              
  |==============================================================================                                                                                          |  47%
  |                                                                                                                                                                              
  |==========================================================================================                                                                              |  53%
  |                                                                                                                                                                              
  |=====================================================================================================                                                                   |  60%
  |                                                                                                                                                                              
  |================================================================================================================                                                        |  67%
  |                                                                                                                                                                              
  |===========================================================================================================================                                             |  73%
  |                                                                                                                                                                              
  |======================================================================================================================================                                  |  80%
  |                                                                                                                                                                              
  |==================================================================================================================================================                      |  87%
  |                                                                                                                                                                              
  |=============================================================================================================================================================           |  93%
  |                                                                                                                                                                              
  |========================================================================================================================================================================| 100%
mclustFits$bic <- map_dbl(mclustFits$mclustFits, ~.x[['bic']])
mclustFits$loglik <- map_dbl(mclustFits$mclustFits, ~.x[['loglik']])
mclustFits
mclustFits %>% 
  xyplot(bic+loglik~as.factor(mclust_clusters),., auto.key = T, type = 'b')

summary(mclustFits[[4,'mclustFits']])
---------------------------------------------------- 
Gaussian finite mixture model fitted by EM algorithm 
---------------------------------------------------- 

Mclust VII (spherical, varying volume) model with 5 components: 

 log.likelihood    n  df       BIC       ICL
      -48851.89 1800 114 -98558.28 -98984.67

Clustering table:
  1   2   3   4   5 
527 317 305 275 376 
mclust_clusters <- mclustFits[[4,'mclustFits']]$classification
clusplot(df_nums_adj, mclust_clusters, color=TRUE, shade=TRUE, labels=4, lines=0, main="M Clust Plot, k = 4")

seg.summ(df_nums_adj, mclust_clusters)
mclust_distMat <- daisy(df_nums_adj)
binary variable(s) 2, 3, 5 treated as interval scaled
plot(silhouette(mclust_clusters,mclust_distMat))

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGhpZ2hsaWdodDogZXNwcmVzc28KICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0aGVtZTogam91cm5hbAotLS0KCmBgYHtyIGxpYnJhcmllc30KbGlicmFyeShjbHVzdGVyKQpsaWJyYXJ5KG1jbHVzdCkKbGlicmFyeShsYXR0aWNlKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShtYXB0cmVlKQpsaWJyYXJ5KG1pY2UpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkobWNsdXN0KQpsaWJyYXJ5KG1pY2UpCmxpYnJhcnkobkZhY3RvcnMpCmxpYnJhcnkocG9MQ0EpCmxpYnJhcnkoUnRzbmUpCmxpYnJhcnkoY29ycnBsb3QpCmBgYAoKIyBVdGlsaXR5IEZ1bmN0aW9ucwpgYGB7cn0KdXRpbGl0eV9oaXN0b2dyYW1wbG90dGVyIDwtIGZ1bmN0aW9uKHgpIHsKICBsYXR0aWNlOjpoaXN0b2dyYW0oIH4geCkKfQpzZWcuc3VtbSA8LSBmdW5jdGlvbihkYXRhLCBncm91cHMpIHsKICBhZ2dyZWdhdGUoZGF0YSwgbGlzdChncm91cHMpLCBmdW5jdGlvbih4KSBtZWFuKGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHgpKSkpCn0KbWlubWF4IDwtIGZ1bmN0aW9uKHgpCnsKICAgIHJldHVybigoeC0gbWluKHgpKSAvKG1heCh4KS1taW4oeCkpKQp9CnBsb3RfYmlfcGxvdHMgPC0gZnVuY3Rpb24oZGYsIHksLi4uKSB7CiAgb2xkLnBhciA9IHBhcigpCiAgcGFyKG1hcj1jKDUsNCw1LDIpKQogIG9uLmV4aXQoZXhwciA9ICdwYXIgPSBvbGQucGFyJykKICBwcmNvbXAoZGYpICU+JSBiaXBsb3QoY29sID0gYygnZ3JheScsICdyZWQnKSwgY2V4ID0gLjgsIG1haW4gPSB5LCAuLi4pCn0KYWRqdXN0X3ExMyA8LSBmdW5jdGlvbihkZil7CiAgZGYgJTw+JSAKICAgIG11dGF0ZShxMTNfdmlzaXRmcmVxX3NvY2lhbD0gKHExM3IxK3ExM3IyK3ExM3IzICtxMTNyMTEpLzQsCiAgICAgICAgICAgcTEzX3Zpc2l0ZnJlcV9tdXNpYyA9IChxMTNyNCtxMTNyNytxMTNyOCArcTEzcjkpLzQsCiAgICAgICAgICAgcTEzX3Zpc2l0ZnJlcV92aWRlbyA9IChxMTNyNStxMTNyNitxMTNyMTArcTEzcjEyKS80KQogIGRmWywhc3RyX2RldGVjdChuYW1lcyhkZiksJ3ExM3InKV0KfQphZGp1c3RfcTI0IDwtIGZ1bmN0aW9uKGRmKXsKICBkZiAlPD4lIAogICAgbXV0YXRlKAogICAgICBxMjRfdGVjaF9wb3NhdHQgPSAocTI0cjErcTI0cjIrcTI0cjMrcTI0cjUrcTI0cjYpLzUsCiAgICAgIHEyNF90ZWNoX2VudGVyID0gKHEyNHI3K3EyNHI4KS8yLAogICAgICBxMjRfdGVjaF9jb21tID0gKHEyNHIxMCtxMjRyMTErcTI0cjEyKS8zLAogICAgICBxMjRfdGVjaF9uZWdhdHYgPSAocTI0cjQrcTI0cjkpLzIKICAgICkKICBkZlssIXN0cl9kZXRlY3QobmFtZXMoZGYpLCdxMjRyJyldCn0KYWRqdXN0X3EyNSA8LSBmdW5jdGlvbihkZil7CiAgZGYgJTw+JSAKICAgIG11dGF0ZSgKICAgICAgcTI1X3Byc25sdHlfbGVhZGVyID0gKHEyNXIxK3EyNXIyK3EyNXIzK3EyNXI0KS80LAogICAgICBxMjVfcHJzbmx0eV9yaXNrICAgPSAocTI1cjUrcTI1cjcrcTI1cjgpLzMsCiAgICAgIHEyNV9wcnNubHR5X2RyaXZlICA9IChxMjVyOStxMjVyMTArcTI1cjExK3EyNXIxMikvNCwKICAgICAgcTI1X3Byc25sdHlfZm9sbG93ZXIgPSBxMjVyNgogICAgKQogIGRmWywhc3RyX2RldGVjdChuYW1lcyhkZiksJ3EyNXInKV0KfQphZGp1c3RfcTI2IDwtIGZ1bmN0aW9uKGRmKXsKICBkZiAlPD4lIAogICAgbXV0YXRlKAogICAgICBxMjZfc2hvcHNhdnZ5X2JhcmdhaW4gPSAgKHEyNnIzK3EyNnI1KS8yLAogICAgICBxMjZfc2hvcHNhdnZ5X2JyYW5kcyA9IChxMjZyMTgrcTI2cjcrcTI2cjEzK3EyNnIxNCtxMjZyMTUpLzUsCiAgICAgIHEyNl9zaG9wc2F2dnlfZWFybjJzcGVuZCA9IChxMjZyMTMrcTI2cjE2K3EyNnI0KS8zLAogICAgICBxMjZfc2hvcHNhdnZ5X2FwcGxvdmVyID0gKHEyNnIxNytxMjZyMTIrcTI2cjEwK3EyNnI4K3EyNnI2K3EyNnI5KS82LAogICAgICBxMjZfc2hvcHNhdnZ5X2NoaWxkcmVuID0gcTI2cjExLAogICAgKQogIGRmWywhc3RyX2RldGVjdChuYW1lcyhkZiksJ3EyNnInKV0KfQphZGp1c3RfcTIgPC0gZnVuY3Rpb24oZGYpewogIGRmICU8PiUKICAgIG11dGF0ZSgKICAgICAgcTJfYXBwbGUgPSBpZmVsc2UocTJyMT09MXxxMnIyPT0xLDEsMCksCiAgICAgIHEyX2FuZHJpb2QgPSBxMnIzLAogICAgICBxMl93aW5kb3dzID0gcTJyNiwKICAgICAgcTJfdGFibGV0ID0gcTJyOCwKICAgICAgcTJfb3RoZXIgPSBpZmVsc2UocTJyND09MXxxMnI1PT0xfHEycjc9PTF8cTJyOT09MSwxLDApCiAgICApCiAgZGZbLCFzdHJfZGV0ZWN0KG5hbWVzKGRmKSwncTJyJyldCn0KYWRqdXN0X3E0IDwtIGZ1bmN0aW9uKGRmKXsKICAgIGRmICU8PiUKICAgIG11dGF0ZSgKICAgICAgcTRfdXNlX211c2ljX2FwcHMgPXE0cjEsCiAgICAgIHE0X3VzZV90dl9hcHBzID1pZmVsc2UocTRyMj09MXxxNHIzPT0xfHE0cjQ9PTEsMSwwKSwKICAgICAgcTRfdXNlX2dhbWVfYXBwcyA9cTRyNSwKICAgICAgcTRfdXNlX3NvY2lhbF9hcHBzID1xNHI2LAogICAgICBxNF91c2VfbmV3c19hcHBzID1pZmVsc2UocTRyNz09MXxxNHI5PT0xLDEsMCksCiAgICAgIHE0X3VzZV9zaG9wX2FwcHMgPXE0cjgsCiAgICAgIHE0X3VzZV9ub25lX2FwcHMgPXE0cjExCiAgICApCiAgZGZbLCFzdHJfZGV0ZWN0KG5hbWVzKGRmKSwncTRyJyldCn0KYWRqdXN0X3JhY2UgPC0gZnVuY3Rpb24oZGYpewogIGRmICU+JSAKICAgIG11dGF0ZSgKICAgICAgcTU0X3doaXRlICA9IGlmZWxzZShxNTQ9PTEsMSwwKSwKICAgICAgcTU0X2JsYWNrICA9IGlmZWxzZShxNTQ9PTIsMSwwKSwKICAgICAgcTU0X2FzaWFuICA9IGlmZWxzZShxNTQ9PTMsMSwwKSwKICAgICAgcTU0X2hhd2FpICA9IGlmZWxzZShxNTQ9PTQsMSwwKSwKICAgICAgcTU0X25hdGl2ZSA9ICBpZmVsc2UocTU0PT01LDEsMCksCiAgICAgIHE1NF9vdGhlciAgPSBpZmVsc2UocTU0PT02LDEsMCksCiAgICAgIHE1NV9sYXRpbm8gPSAgaWZlbHNlKHE1NT09MSwxLDApCiAgICApICU+JSAKICAgIGRwbHlyOjpzZWxlY3QoLXE1NCwtcTU1KQp9CmFkanVzdF9nZW5kZXIgPC0gZnVuY3Rpb24oZGYpewogIGRmICU+JSAKICAgIG11dGF0ZShxNTcgPSBpZmVsc2UocTU3PT0xLDEsMCkpCn0KYWRqdXN0X21hcml0YWwgPC0gZnVuY3Rpb24oZGYpewogIGRmICU+JSAKICAgIG11dGF0ZShxNDkgPSBpZmVsc2UocTQ5PT0xLDEsMCkpCn0KYWRqdXN0X3ExMSA8LSBmdW5jdGlvbihkZil7CiAgI1ExMSBoYXMgYXJ0aWZpY2lhbCBvcmRpbmFsaXR5IGJldHdlZW4gI29mIGFwcHMgaW5jcmVhc2luZywgYW5kIHJlc3BvbnNlPT01IGFzICJEb250IGtub3ciCiAgI1RoaXMgZnVuY3Rpb24gcmVzb2x2ZXMgdGhpcyBwcm9ibGVtCiAgZGYgJT4lIAogICAgbXV0YXRlKHExMSA9IGlmZWxzZShxMTE9PTUgfCBxMTE9PTYsIDAsIHExMSkpCn0KYWRqdXN0X2NoaWxkcmVuIDwtIGZ1bmN0aW9uKGRmKXsKICBkZiAlPiUgCiAgICBkcGx5cjo6c2VsZWN0KC1xNTByMl9pbmZ0b2QsLXE1MHIzXzZfMTIsLXE1MHI0XzEzXzE3LC1xNTByNV9hZHVsdCkKfQphZGp1c3RfaW5jb21lIDwtIGZ1bmN0aW9uKGRmKXsKICBkZiAlPiUgCiAgICBkcGx5cjo6bXV0YXRlKHE1NiA9IGNhc2Vfd2hlbigKICAgICAgcTU2IDw9IDQgfiAxLAogICAgICBxNTYgPj0gNSAmIHE1NiA8PTggfiAyLAogICAgICBxNTYgPj0gOSAmIHE1NiA8PTExIH4gMywKICAgICAgcTU2ID49IDEyICYgcTU2IDw9IDEzIH4gNCwKICAgICAgcTU2ID49IDE0IH4gNQogICAgKSkKfQphZGp1c3RfYWdlIDwtIGZ1bmN0aW9uKGRmKXsKICBkZiAlPiUgCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBxMSA9IGNhc2Vfd2hlbigKICAgICAgICBxMSA8PSAyIH4gMSwKICAgICAgICBxMSA+PSAzICYgcTEgPD0gNSB+IDIsCiAgICAgICAgcTEgPj0gNiAmIHExIDw9IDggfiAzLAogICAgICAgIHExID49IDkgJiBxMSA8PSAxMSB+IDQsCiAgICAgICAgcTEgPj0gMTIgfiA1LAogICAgICApCiAgICApCn0KYWRqdXN0X25hbWVzIDwtIGZ1bmN0aW9uKGRmKXsKICBkZiAlPiUgCiAgICBkcGx5cjo6cmVuYW1lKAogICAgICBxMV9hZ2U9cTEsCiAgICAgIHExMV9hcHBudW0gPSBxMTEsCiAgICAgIHExMl9mcmVlYXBwcGMgPSBxMTIsCiAgICAgIHE0OF9lZHUgPSBxNDgsCiAgICAgIHE0OV9tYXJpdGFsID0gcTQ5LAogICAgICBxNTZfaW5jb21lID0gcTU2LAogICAgICBxNTdfbWYgPSBxNTcsCiAgICAgIHE1MHIxX25vY2hpbGQgPSBxNTByMSwKICAgICAgcTUwcjJfaW5mdG9kID0gcTUwcjIsIAogICAgICBxNTByM182XzEyID0gcTUwcjMsCiAgICAgIHE1MHI0XzEzXzE3ID0gcTUwcjQsCiAgICAgIHE1MHI1X2FkdWx0ID0gcTUwcjUKICAgICkKfQpgYGAKCgojIERhdGEgUHJlcApgYGB7cn0KbG9hZCgnLi4vZGF0YS9hcHBoYXBweURhdGEuUkRhdGEnKQpkZl9sYWJzIDwtIHRibF9kZihhcHBoYXBweS4zLmxhYnMuZnJhbWUpCmRmX251bXMgPC0gdGJsX2RmKGFwcGhhcHB5LjMubnVtLmZyYW1lKQpkaW0oZGZfbnVtcykKcm0oYXBwaGFwcHkuMy5udW0uZnJhbWUpOyBybShhcHBoYXBweS4zLmxhYnMuZnJhbWUpCmRmX2xhYnMkcTU3IDwtIGFzLmZhY3RvcihkZl9sYWJzJHE1NykKZGZfbGFicyRjYXNlSUQgPC0gTlVMTApkZl9udW1zJGNhc2VJRCA8LSBOVUxMCmRmX2xhYnMkcTJyMTAgPC0gTlVMTApkZl9udW1zJHEycjEwIDwtIE5VTEwKZGZfbGFicyRxNXIxIDwtIE5VTEwKZGZfbnVtcyRxNXIxIDwtIE5VTEwKYGBgCgojIFJlbW92ZSBtaXNzaW5nIHZhbHVlcwoKIyMgSGFuZGxlIHRoZSBjYXNlIG9mIHRoZSBtaXNzaW5nIGFwcHM/CmBgYHtyfQpkZl9udW1zJHExMltpcy5uYShkZl9udW1zJHExMildIDwtIDAKZGZfbnVtcyAlPiUgeHRhYnMofnExMitxMTEsLixhZGROQSA9IFQpCmRmX251bXMgJT4lIHh0YWJzKH5xNHIxMCtxMTEsLixhZGROQSA9IFQpCmRmX251bXMgJT4lIHh0YWJzKH5xNHIxMStxMTEsLixhZGROQSA9IFQpCiMgUlVMRSAoQSk6IElGIHE0cjExPVRSVUUsIGl0IG1lYW5zIHlvdSBoYXZlIG5vIGFwcHMuIFNvIHRoYXQgbWVhbnMgcTExIGhhcyB0byBlcXVhbCA2LCBpLmUuIE5PTkUuIERhdGEgc2hvd3MgdGhpcyBpcyB2aW9sYXRlZC4gQ29ycmVjdGluZyB1c2luZyB0aGlzIHJ1bGUuCmRmX251bXMkcTExW2RmX251bXMkcTRyMTE9PVRSVUVdIDwtIDYKZGZfbnVtcyAlPiUgeHRhYnMofnE0cjExK3ExMSwuLGFkZE5BID0gVCkKYGBgCgojIyBTbWFsbCBjaGFuZ2VzCgpTaW5jZSBxMTEgY2FuIGJlIG9yZGluYWwsICJub25lIiBzaG91bGQgZXF1YWwgMCBpbnN0ZWFkIG9mIDYgdG8gcHJlc2VydmUgb3JkaW5hbGl0eQpgYGB7cn0KIyBSVUxFIChCKTogU2V0IHExMT02IHRvIHExMT0wCmRmX251bXMkcTExW2RmX251bXMkcTExPT02XSA8LSAwCmRmX251bXMgJT4lIHh0YWJzKH5xMTEsLiwgYWRkTkEgPSBUKQpgYGAKCidEb250IGtub3cnIGRvZXNuJ3QgYWRkIHZhbHVlLiBQZXJoYXBzIHRoZXNlIGNhbiBiZSBzZXQgdG8gYE5BYCBhbmQgdGhlbiBpbXB1dGVkIHVzaW5nIGBtaWNlYC4KCmBgYHtyfQojIFJVTEUgKEMpOiBTZXQgcTExIERvbnQga25vdyB0byBOQQpkZl9udW1zJHExMVtkZl9udW1zJHExMT09MF0gPC0gTkEKZGZfbnVtcyAlPiUgeHRhYnMofnExMSwuLCBhZGROQSA9IFQpCmBgYAoKYGBge3J9CiMgUlVMRSAoRCk6IEFsbCBOQSB2YWx1ZXMgZm9yIHExMiBzZXQgdG8gNiwgc2luY2UgSSdtIGFwcHJveGltYXRpbmcgdGhhdCBpZiB5b3UgZG9uJ3QgaGF2ZSBhbnkgYXBwcywgbWlnaHQgYXMgd2VsbCBjb3VsZCBhcyBmcmVlPwpkZl9udW1zJHExMltpcy5uYShkZl9udW1zJHExMildIDwtIDYKZGZfbnVtcyAlPiUgeHRhYnMofnExMiwuLCBhZGROQSA9IFQpCmBgYAoKYGBge3J9Cm1hcF9pbnQoZGZfbnVtcyx+c3VtKGlzLm5hKC54KSkpICU+JSBzb3J0KCkgJT4lIHRhaWwoMykgJT4lIGJhcmNoYXJ0KG1haW49J01pc3NpbmcgdmFsdWVzJykKYGBgCgoKIyMgSW1wdXRpbmcgdXNpbmcgYG1pY2VgCmBgYHtyfQptYXBfZGYoZGZfbnVtcyx+YXMuZmFjdG9yKC54KSkgJT4lIAogIG1pY2U6Om1pY2UocHJpbnRGbGFnID0gVCwgbSA9IDUsIG1ldGhvZCA9ICdyZicpIC0+IG1pY2VGaXQKZGZfbnVtcyA8LSB0YmxfZGYobWljZTo6Y29tcGxldGUobWljZUZpdCkpCmBgYAoKIyBCaSBQbG90cwoKYGBge3J9CiMgcXVlc3Rpb25zX3RvX2NvbnNvbGlkYXRlIDwtIGMoJ3ExMycsJ3EyNCcsJ3EyNScsJ3EyNicpCiMgcGxvdF9iaV9wbG90cyhkZl9udW1zICU+JSBkcGx5cjo6c2VsZWN0KGNvbnRhaW5zKHF1ZXN0aW9uc190b19jb25zb2xpZGF0ZVsxXSkpLHF1ZXN0aW9uc190b19jb25zb2xpZGF0ZVsxXSkKIyBwbG90X2JpX3Bsb3RzKGRmX251bXMgJT4lIGRwbHlyOjpzZWxlY3QoY29udGFpbnMocXVlc3Rpb25zX3RvX2NvbnNvbGlkYXRlWzJdKSkscXVlc3Rpb25zX3RvX2NvbnNvbGlkYXRlWzJdLCB4bGltPWMoMCwuMDUpLCB5bGltPWMoLTAuMDEsMC4wMDIpKQojIHBsb3RfYmlfcGxvdHMoZGZfbnVtcyAlPiUgZHBseXI6OnNlbGVjdChjb250YWlucyhxdWVzdGlvbnNfdG9fY29uc29saWRhdGVbM10pKSxxdWVzdGlvbnNfdG9fY29uc29saWRhdGVbM10pCiMgcGxvdF9iaV9wbG90cyhkZl9udW1zICU+JSBkcGx5cjo6c2VsZWN0KGNvbnRhaW5zKHF1ZXN0aW9uc190b19jb25zb2xpZGF0ZVs0XSkpLHF1ZXN0aW9uc190b19jb25zb2xpZGF0ZVs0XSwgeGxpbT1jKDAsMC4wNSkseWxpbT1jKC0wLjAxMSwwLjAwNSkpCmBgYAoKIyBEYXRhIFByZXAKCiMjIFN1YiBncm91cGluZwoKYGBge3J9CmRmX251bXMgPC0gbWFwX2RmKGRmX251bXMsfmFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKC54KSkpCmRmX251bXNfYWRqIDwtIGRmX251bXMgJT4lICAKICBhZGp1c3RfcTEzKCkgJT4lIAogIGFkanVzdF9xMjQoKSAlPiUgCiAgYWRqdXN0X3EyNSgpICU+JSAKICBhZGp1c3RfcTI2KCkgJT4lIAogIGFkanVzdF9xMigpICU+JSAKICBhZGp1c3RfcTQoKSAlPiUgCiAgYWRqdXN0X3JhY2UoKSAlPiUgCiAgYWRqdXN0X2dlbmRlcigpICU+JSAKICBhZGp1c3RfbWFyaXRhbCgpICU+JSAKICBhZGp1c3RfaW5jb21lKCkgJT4lCiAgYWRqdXN0X2FnZSgpICU+JSAKICBhZGp1c3RfcTExKCkgJT4lIAogIGFkanVzdF9uYW1lcygpICU+JSAKICBhZGp1c3RfY2hpbGRyZW4oKQoKZ2xpbXBzZShkZl9udW1zX2FkaikKYGBgCgojIyBTZWxlY3Rpb24gb2YgYmFzaXMgdmFyaWFibGVzCgpgYGB7cn0Kc2V0MSA8LSBjKAogICdxMV9hZ2UnLAogICMgJ3ExMV9hcHBudW0nLAogICMgJ3ExMl9mcmVlYXBwcGMnLAogICdxNDhfZWR1JywKICAncTQ5X21hcml0YWwnLAogICdxNTByMV9ub2NoaWxkJywKICAncTU2X2luY29tZScsCiAgIyAncTU3X21mJywKICAjICdxMTNfdmlzaXRmcmVxX3NvY2lhbCcsCiAgIyAncTEzX3Zpc2l0ZnJlcV9tdXNpYycsCiAgIyAncTEzX3Zpc2l0ZnJlcV92aWRlbycsCiAgJ3EyNF90ZWNoX3Bvc2F0dCcsCiAgJ3EyNF90ZWNoX2VudGVyJywKICAncTI0X3RlY2hfY29tbScsCiAgJ3EyNF90ZWNoX25lZ2F0dicsCiAgIyAncTI1X3Byc25sdHlfbGVhZGVyJywKICAjICdxMjVfcHJzbmx0eV9yaXNrJywKICAjICdxMjVfcHJzbmx0eV9kcml2ZScsCiAgIyAncTI1X3Byc25sdHlfZm9sbG93ZXInLAogICdxMjZfc2hvcHNhdnZ5X2JhcmdhaW4nLAogICdxMjZfc2hvcHNhdnZ5X2JyYW5kcycsCiAgJ3EyNl9zaG9wc2F2dnlfZWFybjJzcGVuZCcsCiAgJ3EyNl9zaG9wc2F2dnlfYXBwbG92ZXInLAogICdxMjZfc2hvcHNhdnZ5X2NoaWxkcmVuJywKICAncTJfYXBwbGUnLAogICdxMl9hbmRyaW9kJywKICAncTJfd2luZG93cycsCiAgIyAncTJfdGFibGV0JywKICAjICdxMl9vdGhlcicsCiAgIyAncTRfdXNlX211c2ljX2FwcHMnLAogICMgJ3E0X3VzZV90dl9hcHBzJywKICAjICdxNF91c2VfZ2FtZV9hcHBzJywKICAjICdxNF91c2Vfc29jaWFsX2FwcHMnLAogICMgJ3E0X3VzZV9uZXdzX2FwcHMnLAogICMgJ3E0X3VzZV9zaG9wX2FwcHMnLAogICMgJ3E0X3VzZV9ub25lX2FwcHMnLAogICdxNTRfd2hpdGUnLAogICdxNTRfYmxhY2snLAogICdxNTRfYXNpYW4nLAogICdxNTRfaGF3YWknLAogICdxNTRfbmF0aXZlJywKICAjICdxNTRfb3RoZXInLAogICdxNTVfbGF0aW5vJwogICkKc2V0MiA8LSBjKAogICdxMV9hZ2UnLAogICMgJ3ExMV9hcHBudW0nLAogICdxMTJfZnJlZWFwcHBjJywKICAncTQ4X2VkdScsCiAgJ3E0OV9tYXJpdGFsJywKICAncTUwcjFfbm9jaGlsZCcsCiAgJ3E1Nl9pbmNvbWUnLAogICMgJ3E1N19tZicsCiAgJ3ExM192aXNpdGZyZXFfc29jaWFsJywKICAncTEzX3Zpc2l0ZnJlcV9tdXNpYycsCiAgJ3ExM192aXNpdGZyZXFfdmlkZW8nLAogICdxMjRfdGVjaF9wb3NhdHQnLAogICdxMjRfdGVjaF9lbnRlcicsCiAgJ3EyNF90ZWNoX2NvbW0nLAogICdxMjRfdGVjaF9uZWdhdHYnLAogICdxMjVfcHJzbmx0eV9sZWFkZXInLAogICdxMjVfcHJzbmx0eV9yaXNrJywKICAncTI1X3Byc25sdHlfZHJpdmUnLAogICdxMjVfcHJzbmx0eV9mb2xsb3dlcicsCiAgJ3EyNl9zaG9wc2F2dnlfYmFyZ2FpbicsCiAgJ3EyNl9zaG9wc2F2dnlfYnJhbmRzJywKICAncTI2X3Nob3BzYXZ2eV9lYXJuMnNwZW5kJywKICAncTI2X3Nob3BzYXZ2eV9hcHBsb3ZlcicsCiAgJ3EyNl9zaG9wc2F2dnlfY2hpbGRyZW4nLAogICMgJ3EyX2FwcGxlJywKICAjICdxMl9hbmRyaW9kJywKICAjICdxMl93aW5kb3dzJywKICAjICdxMl90YWJsZXQnLAogICMgJ3EyX290aGVyJywKICAjICdxNF91c2VfbXVzaWNfYXBwcycsCiAgIyAncTRfdXNlX3R2X2FwcHMnLAogICMgJ3E0X3VzZV9nYW1lX2FwcHMnLAogICMgJ3E0X3VzZV9zb2NpYWxfYXBwcycsCiAgIyAncTRfdXNlX25ld3NfYXBwcycsCiAgIyAncTRfdXNlX3Nob3BfYXBwcycsCiAgIyAncTRfdXNlX25vbmVfYXBwcycsCiAgJ3E1NF93aGl0ZScsCiAgJ3E1NF9ibGFjaycsCiAgJ3E1NF9hc2lhbicsCiAgJ3E1NF9oYXdhaScsCiAgJ3E1NF9uYXRpdmUnLAogICMgJ3E1NF9vdGhlcicsCiAgJ3E1NV9sYXRpbm8nCiAgKQpzZXQzIDwtIGMoCiAgJ3ExX2FnZScsCiAgJ3ExMV9hcHBudW0nLAogICdxMTJfZnJlZWFwcHBjJywKICAncTQ4X2VkdScsCiAgJ3E0OV9tYXJpdGFsJywKICAncTUwcjFfbm9jaGlsZCcsCiAgJ3E1Nl9pbmNvbWUnLAogICdxNTdfbWYnLAogICMgJ3ExM192aXNpdGZyZXFfc29jaWFsJywKICAjICdxMTNfdmlzaXRmcmVxX211c2ljJywKICAjICdxMTNfdmlzaXRmcmVxX3ZpZGVvJywKICAjICdxMjRfdGVjaF9wb3NhdHQnLAogICMgJ3EyNF90ZWNoX2VudGVyJywKICAjICdxMjRfdGVjaF9jb21tJywKICAjICdxMjRfdGVjaF9uZWdhdHYnLAogICMgJ3EyNV9wcnNubHR5X2xlYWRlcicsCiAgIyAncTI1X3Byc25sdHlfcmlzaycsCiAgIyAncTI1X3Byc25sdHlfZHJpdmUnLAogICMgJ3EyNV9wcnNubHR5X2ZvbGxvd2VyJywKICAncTI2X3Nob3BzYXZ2eV9iYXJnYWluJywKICAncTI2X3Nob3BzYXZ2eV9icmFuZHMnLAogICdxMjZfc2hvcHNhdnZ5X2Vhcm4yc3BlbmQnLAogICdxMjZfc2hvcHNhdnZ5X2FwcGxvdmVyJywKICAncTI2X3Nob3BzYXZ2eV9jaGlsZHJlbicsCiAgJ3EyX2FwcGxlJywKICAncTJfYW5kcmlvZCcsCiAgJ3EyX3dpbmRvd3MnLAogICdxMl90YWJsZXQnLAogICdxMl9vdGhlcicsCiAgJ3E0X3VzZV9tdXNpY19hcHBzJywKICAncTRfdXNlX3R2X2FwcHMnLAogICdxNF91c2VfZ2FtZV9hcHBzJywKICAncTRfdXNlX3NvY2lhbF9hcHBzJywKICAncTRfdXNlX25ld3NfYXBwcycsCiAgJ3E0X3VzZV9zaG9wX2FwcHMnLAogICdxNF91c2Vfbm9uZV9hcHBzJwogICMgJ3E1NF93aGl0ZScsCiAgIyAncTU0X2JsYWNrJywKICAjICdxNTRfYXNpYW4nLAogICMgJ3E1NF9oYXdhaScsCiAgIyAncTU0X25hdGl2ZScsCiAgIyAncTU0X290aGVyJywKICAjICdxNTVfbGF0aW5vJwogICkKc2V0NCA8LSBjKAogICdxMV9hZ2UnLAogICMgJ3ExMV9hcHBudW0nLAogICMgJ3ExMl9mcmVlYXBwcGMnLAogICMgJ3E0OF9lZHUnLAogICdxNDlfbWFyaXRhbCcsCiAgJ3E1MHIxX25vY2hpbGQnLAogICdxNTZfaW5jb21lJywKICAncTU3X21mJywKICAncTEzX3Zpc2l0ZnJlcV9zb2NpYWwnLAogICdxMTNfdmlzaXRmcmVxX211c2ljJywKICAncTEzX3Zpc2l0ZnJlcV92aWRlbycsCiAgJ3EyNF90ZWNoX3Bvc2F0dCcsCiAgJ3EyNF90ZWNoX2VudGVyJywKICAncTI0X3RlY2hfY29tbScsCiAgJ3EyNF90ZWNoX25lZ2F0dicsCiAgJ3EyNV9wcnNubHR5X2xlYWRlcicsCiAgJ3EyNV9wcnNubHR5X3Jpc2snLAogICdxMjVfcHJzbmx0eV9kcml2ZScsCiAgJ3EyNV9wcnNubHR5X2ZvbGxvd2VyJywKICAncTI2X3Nob3BzYXZ2eV9iYXJnYWluJywKICAncTI2X3Nob3BzYXZ2eV9icmFuZHMnLAogICdxMjZfc2hvcHNhdnZ5X2Vhcm4yc3BlbmQnLAogICdxMjZfc2hvcHNhdnZ5X2FwcGxvdmVyJywKICAncTI2X3Nob3BzYXZ2eV9jaGlsZHJlbicKICAjICdxMl9hcHBsZScsCiAgIyAncTJfYW5kcmlvZCcsCiAgIyAncTJfd2luZG93cycsCiAgIyAncTJfdGFibGV0JywKICAjICdxMl9vdGhlcicsCiAgIyAncTRfdXNlX211c2ljX2FwcHMnLAogICMgJ3E0X3VzZV90dl9hcHBzJywKICAjICdxNF91c2VfZ2FtZV9hcHBzJywKICAjICdxNF91c2Vfc29jaWFsX2FwcHMnLAogICMgJ3E0X3VzZV9uZXdzX2FwcHMnLAogICMgJ3E0X3VzZV9zaG9wX2FwcHMnLAogICMgJ3E0X3VzZV9ub25lX2FwcHMnCiAgIyAncTU0X3doaXRlJywKICAjICdxNTRfYmxhY2snLAogICMgJ3E1NF9hc2lhbicsCiAgIyAncTU0X2hhd2FpJywKICAjICdxNTRfbmF0aXZlJywKICAjICdxNTRfb3RoZXInLAogICMgJ3E1NV9sYXRpbm8nCiAgKQpgYGAKCmBgYHtyfQpkZl9udW1zX2Fkal9iYWNrdXAgPC0gZGZfbnVtc19hZGoKYGBgCmBgYHtyfQpkZl9udW1zX2FkaiA8LSBkZl9udW1zX2Fkal9iYWNrdXAKYGBgCgpgYGB7cn0KZGZfbnVtc19hZGogPC0gZGZfbnVtc19hZGogJT4lIGRwbHlyOjpzZWxlY3Qob25lX29mKHNldDQpKQpgYGAKCgojIFNjYWxpbmcKYGBge3J9CnNjYWxpbmdfd2FudGVkIDwtIFQKbWlubWF4X3dhbnRlZCA8LSBGCmlmIChzY2FsaW5nX3dhbnRlZCkgewogIGRmX251bXNfYWRqc2NhbGVkIDwtIHNjYWxlKGRmX251bXNfYWRqKQogIGNlbnRlcnMgPC0gYXR0cmlidXRlcyhkZl9udW1zX2FkanNjYWxlZClbWzNdXQogIHNwcmVhZHMgPC0gYXR0cmlidXRlcyhkZl9udW1zX2FkanNjYWxlZClbWzRdXQogIGRmX251bXNfYWRqc2NhbGVkIDwtIHRibF9kZihkZl9udW1zX2FkanNjYWxlZCkKfQppZihtaW5tYXhfd2FudGVkKXsKICBkZl9udW1zX2FkanNjYWxlZCA8LSBtYXBfZGYoZGZfbnVtc19hZGosIH5taW5tYXgoLngpKQp9CmlmKCFzY2FsaW5nX3dhbnRlZCAmICFtaW5tYXhfd2FudGVkKXsKICBkZl9udW1zX2FkanNjYWxlZCA8LSBkZl9udW1zX2Fkagp9CmhlYWQoZGZfbnVtc19hZGpzY2FsZWQpCmBgYAoKIyBDb3JyZWxhdGlvbiBQbG90CmBgYHtyfQpkZl9udW1zX2FkanNjYWxlZCAlPiUgY29yKCkgJT4lIGNvcnJwbG90KG1ldGhvZCA9ICdzaGFkZScsdGwuY29sID0gJ2JsYWNrJyx0bC5jZXggPSAuOSwgb3JkZXIgPSAnaGNsdXN0JywgaGNsdXN0Lm1ldGhvZCA9ICd3YXJkLkQyJykKYGBgCgojIERpc3NpbWlsYXJpdHkgQ2FsY3VsYXRpb25zCgpgYGB7cn0KIyBvcmRlcmVkPWMoMTo0LDExLDEzOjI4KQojIHN5bW1fYmluPWMoNjoxMCwxMiwyOTo0NykKIyBkZl9udW1zX2FkanNjYWxlZFtvcmRlcmVkXSA8LSBtYXBfZGYoZGZfbnVtc19hZGpzY2FsZWRbb3JkZXJlZF0sfmFzLm9yZGVyZWQoLngpKQojIGRmX251bXNfYWRqc2NhbGVkW3N5bW1fYmluXSA8LSBtYXBfZGYoZGZfbnVtc19hZGpzY2FsZWRbc3ltbV9iaW5dLH5hcy5mYWN0b3IoLngpKQpkaXN0TWF0IDwtIGRhaXN5KGRmX251bXNfYWRqc2NhbGVkKQpgYGAKCgojIFNpbXBsZSBjbHVzdGVyaW5nCgojIyBIIGNsdXN0CgojIyMgSG93IGNvcGhlbmV0aWMgY2hhbmdlcyB3aXRoIGNsdXN0ZXJpbmcgbWV0aG9kPwpgYGB7cn0KbWV0aG9kcyA8LSBjKCdjb21wbGV0ZScsJ2F2ZXJhZ2UnLCd3YXJkLkQnLCd3YXJkLkQyJywnbWVkaWFuJywnbWNxdWl0dHknLCdjZW50cm9pZCcpCm1ldGhvZF92c19jb3AgPC0gbWFwX2RibChtZXRob2RzLH5jb3IoY29waGVuZXRpYyhoY2x1c3QoZCA9IGRpc3RNYXQsIG1ldGhvZCA9IC54KSksIGRpc3RNYXQpKQpuYW1lcyhtZXRob2RfdnNfY29wKSA8LSBtZXRob2RzCmJhcmNoYXJ0KHNvcnQobWV0aG9kX3ZzX2NvcCkpCmBgYAoKYGBge3J9CmsgPSA2CmhjbHVzdEZpdCA8LSBoY2x1c3QoZCA9IGRpc3RNYXQsIG1ldGhvZCA9ICd3YXJkLkQnKQpwbG90KGhjbHVzdEZpdCwgbGFiZWxzID0gRikKcmVjdC5oY2x1c3QoaGNsdXN0Rml0LCBrPWssIGJvcmRlcj0icmVkIikKYGBgCgoKYGBge3J9CmhjbHVzdF9zZWdtZW50cyA8LSBjdXRyZWUoaGNsdXN0Rml0LCBrID0gaykKdGFibGUoaGNsdXN0X3NlZ21lbnRzKQpjbHVzcGxvdChkZl9udW1zX2FkanNjYWxlZCwgaGNsdXN0X3NlZ21lbnRzLCBjb2xvcj1UUlVFLCBzaGFkZT1UUlVFLCBsYWJlbHM9NCwgbGluZXM9MCwgbWFpbj0iSENsdXN0IHBsb3QiKQpgYGAKCmBgYHtyfQpzZWcuc3VtbShkZl9udW1zX2FkaiwgaGNsdXN0X3NlZ21lbnRzKSAtPiBjZW50cm9pZHMKY2VudHJvaWRzCmBgYAoKYGBge3J9CmN1dEZpdCA8LSBjdXRyZWUoaGNsdXN0Rml0LCBrKQpwbG90KHNpbGhvdWV0dGUoY3V0Rml0LGRpc3RNYXQpKQpgYGAKYGBge3J9CmsgPC0gMjoxMAp3aWR0aHMgPC0gTlVMTApmb3Ioa18gaW4gayl7CiAgaGNsdXN0Rml0IDwtIGhjbHVzdChkID0gZGlzdE1hdCwgbWV0aG9kID0gJ3dhcmQuRCcpCiAgY3V0Rml0IDwtIGN1dHJlZShoY2x1c3RGaXQsIGtfKQogIHdpZHRocyA8LSBjKHdpZHRocyxtZWFuKHNpbGhvdWV0dGUoY3V0Rml0LGRpc3RNYXQpWywnc2lsX3dpZHRoJ10pKQp9CnBsb3Qoayx3aWR0aHMsdHlwZT0nYicpCmNiaW5kKGssd2lkdGhzKQpgYGAKCgojIyBLLW1lYW5zCgojIyMgSG93IG1hbnkgY2x1c3RlcnMgdG8gdXNlPwoKYGBge3J9Cndzc3Bsb3QgPC0gZnVuY3Rpb24obnVtc3ViLCBuYz0xNSwgc2VlZD0xMTExKSB7CiAgd3NzIDwtIChucm93KG51bXN1YiktMSkqc3VtKGFwcGx5KG51bXN1YiwyLHZhcikpCiAgZm9yIChpIGluIDI6bmMpIHsKICAgIHNldC5zZWVkKHNlZWQpCiAgICB3c3NbaV0gPC0gc3VtKGttZWFucyhudW1zdWIsIGNlbnRlcnM9aSwgaXRlci5tYXggPSAxZTQpJHdpdGhpbnNzKX0KICBwbG90KDE6bmMsIHdzcywgdHlwZT0iYiIsIHhsYWI9Ik51bWJlciBvZiBDbHVzdGVycyIsCiAgICAgICB5bGFiPSJXaXRoaW4gZ3JvdXBzIHN1bSBvZiBzcXVhcmVzIil9Cndzc3Bsb3QoZGZfbnVtc19hZGpzY2FsZWQpCmBgYAoKIyMjIFNvbHZpbmcgdGhlIGstbWVhbnMgbW9kZWwKCmBgYHtyfQprIDwtIDI6MTAKd2lkdGhzIDwtIE5VTEwKZm9yKGtfIGluIGspewogIGNsdXN0ZXJyZXN1bHRzIDwtIGttZWFucyh4ID0gZGZfbnVtc19hZGpzY2FsZWQsIGNlbnRlcnMgPSBrXywgbnN0YXJ0ID0gMzApCiAgd2lkdGhzIDwtIGMod2lkdGhzLG1lYW4oc2lsaG91ZXR0ZShjbHVzdGVycmVzdWx0cyRjbHVzdGVyLGRpc3RNYXQpWywnc2lsX3dpZHRoJ10pKQp9CnBsb3Qoayx3aWR0aHMsdHlwZT0nYicpCmNiaW5kKGssd2lkdGhzKQpgYGAKCmBgYHtyfQojIFVzaW5nIGNsdXN0ZXIgY2VudGVycyBmcm9tIGhjbHVzdDoKc2VnLnN1bW0oZGZfbnVtc19hZGpzY2FsZWQsIGhjbHVzdF9zZWdtZW50cykgLT4ga21lYW5zX2NlbnRyb2lkcwpjbHVzdGVycmVzdWx0cyA8LSBrbWVhbnMoeCA9IGRmX251bXNfYWRqc2NhbGVkLCBjZW50ZXJzID0ga21lYW5zX2NlbnRyb2lkc1ssLTFdKQpyc3F1YXJlIDwtIGNsdXN0ZXJyZXN1bHRzJGJldHdlZW5zcy9jbHVzdGVycmVzdWx0cyR0b3RzcwpjYXQoJ1xuV2l0aGluIFNTOicsY2x1c3RlcnJlc3VsdHMkd2l0aGluc3MsJyBTaXplczpcbicsY2x1c3RlcnJlc3VsdHMkc2l6ZSwnXG5yc3E6JywgcnNxdWFyZSkKY2x1c3Bsb3QoZGZfbnVtc19hZGpzY2FsZWQsIGNsdXN0ZXJyZXN1bHRzJGNsdXN0ZXIsIGNvbG9yPVRSVUUsIHNoYWRlPVRSVUUsIGxhYmVscz00LCBsaW5lcz0wLCBtYWluPSJLLW1lYW5zIGNsdXN0ZXIgcGxvdCIpCnBsb3Qoc2lsaG91ZXR0ZShjbHVzdGVycmVzdWx0cyRjbHVzdGVyLGRpc3RNYXQpKQoKIyBVc2luZyBudW1iZXIgb2YgY2x1c3RlcnMgKyByYW5kb20gc3RhcnRzCmtfa21lYW5zID0gNgpjbHVzdGVycmVzdWx0cyA8LSBrbWVhbnMoeCA9IGRmX251bXNfYWRqc2NhbGVkLCBjZW50ZXJzID0ga19rbWVhbnMpCnJzcXVhcmUgPC0gY2x1c3RlcnJlc3VsdHMkYmV0d2VlbnNzL2NsdXN0ZXJyZXN1bHRzJHRvdHNzCmNhdCgnXG5XaXRoaW4gU1M6JyxjbHVzdGVycmVzdWx0cyR3aXRoaW5zcywnIFNpemVzOlxuJyxjbHVzdGVycmVzdWx0cyRzaXplLCdcbnJzcTonLCByc3F1YXJlKQpjbHVzcGxvdChkZl9udW1zX2FkanNjYWxlZCwgY2x1c3RlcnJlc3VsdHMkY2x1c3RlciwgY29sb3I9VFJVRSwgc2hhZGU9VFJVRSwgbGFiZWxzPTQsIGxpbmVzPTAsIG1haW49IkstbWVhbnMgY2x1c3RlciBwbG90IikKcGxvdChzaWxob3VldHRlKGNsdXN0ZXJyZXN1bHRzJGNsdXN0ZXIsZGlzdE1hdCkpCmBgYAoKYGBge3J9CnNlZy5zdW1tKGRmX251bXNfYWRqLCBjbHVzdGVycmVzdWx0cyRjbHVzdGVyKSAtPiBzZWdzdW1tYXJ5X3Jlc3VsdHMKc2Vnc3VtbWFyeV9yZXN1bHRzICU+JSB3cml0ZV9jc3YocGF0aCA9ICcuLi9yZXBvcnRzL2ttZWFuc19yZXN1bHRzLmNzdicsIGNvbF9uYW1lcyA9IFQpCnNlZ3N1bW1hcnlfcmVzdWx0cwpgYGAKYGBge3J9CmttZWFuc19yZXN1bHRzIDwtIGRmX251bXNfYWRqICU+JSAKICBtdXRhdGUoY2x1c3RlciA9IGNsdXN0ZXJyZXN1bHRzJGNsdXN0ZXIpCgpwdXJycjo6bWFwMihrbWVhbnNfcmVzdWx0cywgbmFtZXMoa21lYW5zX3Jlc3VsdHMpLAogICAgICAgICAgICB+YndwbG90KGNsdXN0ZXJ+LngsIGttZWFuc19yZXN1bHRzLAogICAgICAgICAgICAgICAgICAgIG1haW49LnkpKQpgYGAKCiMjIFBBTQoKYGBge3J9CnBhbUZpdHMgPC0gdGliYmxlKGtfcGFtID0gMjoxMCkKcGFtRml0cyRwYW1GaXRzIDwtIG1hcChwYW1GaXRzJGtfcGFtLCB+cGFtKGRmX251bXNfYWRqc2NhbGVkLCBrID0gLngpKQpwYW1GaXRzJHNpbF9hdmdfd2lkdGggPC0gbWFwX2RibChwYW1GaXRzJHBhbUZpdHMsfi54JHNpbGluZm8kYXZnLndpZHRoKQpwYW1GaXRzCmBgYAoKYGBge3J9CnBhbUZpdHMgJT4lIAogIHh5cGxvdChzaWxfYXZnX3dpZHRofmFzLmZhY3RvcihrX3BhbSksLix0eXBlPSdiJykKYGBgCgpgYGB7cn0KcGxvdChwYW1GaXRzJHBhbUZpdHNbWzFdXSkKYGBgCgpgYGB7cn0Kc2VnLnN1bW0oZGZfbnVtc19hZGosIHBhbUZpdHMkcGFtRml0c1tbMV1dJGNsdXN0ZXJpbmcpCmBgYAoKIyBNb2RlbCBiYXNlZAoKYGBge3J9Cm1jbHVzdEZpdHMgPC0gdGliYmxlKG1jbHVzdF9jbHVzdGVycz0yOjgpCm1jbHVzdEZpdHMkbWNsdXN0Rml0cyA8LSBtYXAobWNsdXN0Rml0cyRtY2x1c3RfY2x1c3RlcnMsIH5NY2x1c3QoZGZfbnVtc19hZGpzY2FsZWQsIEcgPSAueCkpCm1jbHVzdEZpdHMkYmljIDwtIG1hcF9kYmwobWNsdXN0Rml0cyRtY2x1c3RGaXRzLCB+LnhbWydiaWMnXV0pCm1jbHVzdEZpdHMkbG9nbGlrIDwtIG1hcF9kYmwobWNsdXN0Rml0cyRtY2x1c3RGaXRzLCB+LnhbWydsb2dsaWsnXV0pCm1jbHVzdEZpdHMKYGBgCgpgYGB7cn0KbWNsdXN0Rml0cyAlPiUgCiAgeHlwbG90KGJpYytsb2dsaWt+YXMuZmFjdG9yKG1jbHVzdF9jbHVzdGVycyksLiwgYXV0by5rZXkgPSBULCB0eXBlID0gJ2InKQpgYGAKCmBgYHtyfQpzdW1tYXJ5KG1jbHVzdEZpdHNbWzQsJ21jbHVzdEZpdHMnXV0pCmBgYAoKYGBge3J9Cm1jbHVzdF9jbHVzdGVycyA8LSBtY2x1c3RGaXRzW1s0LCdtY2x1c3RGaXRzJ11dJGNsYXNzaWZpY2F0aW9uCmNsdXNwbG90KGRmX251bXNfYWRqLCBtY2x1c3RfY2x1c3RlcnMsIGNvbG9yPVRSVUUsIHNoYWRlPVRSVUUsIGxhYmVscz00LCBsaW5lcz0wLCBtYWluPSJNIENsdXN0IFBsb3QsIGsgPSA0IikKYGBgCgpgYGB7cn0Kc2VnLnN1bW0oZGZfbnVtc19hZGosIG1jbHVzdF9jbHVzdGVycykKYGBgCmBgYHtyfQptY2x1c3RfZGlzdE1hdCA8LSBkYWlzeShkZl9udW1zX2FkaikKcGxvdChzaWxob3VldHRlKG1jbHVzdF9jbHVzdGVycyxtY2x1c3RfZGlzdE1hdCkpCmBgYAoKPCEtLSAjIyB0c25lIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gdHNuZUZpdCA8LSBSdHNuZTo6UnRzbmUoWCA9IGFzLm1hdHJpeChkZl9udW1zX2FkanNjYWxlZCksIHBlcnBsZXhpdHkgPSA0MCwgbWF4X2l0ZXIgPSA1MDAwLCBwY2EgPSBGQUxTRSwgbW9tZW50dW0gPSAwLjc1KSAtLT4KPCEtLSB0c25lRml0IC0tPgo8IS0tIHRvUGxvdCA8LSB0YmxfZGYodHNuZUZpdCRZKSAtLT4KPCEtLSBuYW1lcyh0b1Bsb3QpIDwtIGMoJ1gnLCdZJykgLS0+CjwhLS0geHlwbG90KFh+WSwgZGF0YSA9IHRvUGxvdCkgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gZGZfbnVtc19hZGogJT4lIGJpbmRfY29scyh0b1Bsb3QpICU+JSAgLS0+CjwhLS0gICBsYXR0aWNlOjp4eXBsb3QoWX5YLGdyb3Vwcz1xMTNfdmlzaXRmcmVxX3ZpZGVvLGRhdGE9LixhdXRvLmtleT1saXN0KGNvbHVtbnM9NikpIC0tPgo8IS0tIGBgYCAtLT4KCjwhLS0gYGBge3J9IC0tPgo8IS0tIGRmX251bXNfYWRqICU+JSBiaW5kX2NvbHModG9QbG90KSAlPiUgd3JpdGVfY3N2KHBhdGggPSAnLi4vZGF0YS90c25lX291dC5jc3YnLCBjb2xfbmFtZXMgPSBUKSAtLT4KPCEtLSBgYGAgLS0+Cgo=